﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ClassLibrary1
{
    //结构

    //1、什么时是结构
    //  结构（Structure）是一种用户定义的值类型（Value Type）。它类似于类（Class），但有一些重要的区别。
    //  结构在C#中用struct关键字定义，并且通常用于表示简单的数据结构，如坐标、日期、时间等。与类不同，结构是值类型，
    //  而不是引用类型。这意味着结构的实例在被赋值或传递给其他变量时会被复制，而不是传递引用。


    //结构的特点包括
    /// 值类型：    结构是值类型，它存储在栈上，并直接包含其数据。当结构被赋值给另一个变量或作为参数传递时，将进行值的复制。
    /// 默认构造函数：     结构可以有自己的构造函数，但如果没有显式定义构造函数，编译器会为其提供一个默认的无参构造函数。
    /// 不支持继承：      结构不支持类的继承，它们不能作为其他结构或类的基类。
    /// 值语义：        结构具有值语义，即可以使用==和!=运算符进行比较，按值进行相等性比较。
    /// 栈分配：        结构的实例通常分配在栈上，这使得它们的创建和销毁速度更快。
    /// 适用于小型数据：    由于结构被存储在栈上，所以通常适用于包含少量数据的情况，当数据较大时，使用类更为合适。
    /// 


    //2、创建和使用结构
    //  前面介绍了类如何封装程序中的对象，也介绍了如何将它们存储在堆中，通过这种方式可以在数据的生存期上获得很大的灵活性，但性能会有一定损失。
    //    因为托管堆的优化，这种性能损失较小。但是，有时仅需要一个小的数据结构。此时，类提供的功能多于我们需要的功能，由于性能原因，最好使用结构。

    //类的创建
    public class Dimensions
    {
        //类构造函数
        public Dimensions(double length, double width)
        {
            Length = length;
            Width = width;
        }

        public double Length { get; set; }
        public double Width { get; set; }
       
    }

    /// <summary>
    /// 上面的代码定义了类 Dimensions，它只存储了某一项的长度和宽度。
    /// 假定编写一个布置家具的程序，让人们试着在计算机上重新布置家具，并存储每件家具的尺寸。
    /// 表面看来使字段变为公共字段会违背编程规则，但这里的关键是我们实际上并不需要类的全部功能。
    /// 现在只有两个数字，把它们当成一对来处理，要比单个处理方便一些。
    /// 既不需要很多方法，也不需要从类中继承，也不希望 .NET运行库在堆中遇到麻烦和性能问题，只需要存储两个 double 类型的数据即可。
    /// 此时，只需要修改代码，用关键字 struct 代替 class，定义一个结构而不是类
    /// </summary>
    public struct DimensionsStruct
    {

        //结构体静态给构造
        static DimensionsStruct()
        {

        }
        //结构构造函数
        public DimensionsStruct(double length, double width)
        {
            Length = length;
            Width = width;
        }
        //结构中的属性
        public double Length { set; get; }
        public double Width { set; get; }

        //结构可自带方法
        public double Diagonal()
        {
            return Math.Sqrt(Length * Length + Width * Width);
        }
    }


    //  结构是值类型不是引用类型，它们存储在栈中，或存储为内联（如他们是存储在堆中的另一个对象的一部分），其生存期的限制与简单的数据类型一样。
    //  结构不支持继承
    //  可以实现接口
    //  对于结构构造函数的工作方式有一些区别。如果没有提供默认的构造函数，编译器会自动提供一个，把成员初始化为其默认值。
    //  使用结构可以指定字段如何在内存中布局




    //3、类和结构之间的区别

    //  3.1、结构是值类型
    //      虽然结构是值类型，但在语法上尝尝可以把他们当作类来处理。
    public class demo
    {
        public void Method()
        {
            //声明结构型变量
            DimensionsStruct point = new DimensionsStruct();
            point.Width = 6;
            point.Length = 3;
        }
        //注意   因为结构是值类型，所以new运算符和其他引用类型的工作方式不同。此时，new 运算符并不分配堆中的内存，而是只调用相应的构造函数，
        //          根据传送给他的参数，初始化所有字段。
        //          所以，结构变量的声明和初始化也可以像下面这样写
        public void Method1()
        {
            DimensionsStruct point=new DimensionsStruct();
            point.Length = 6;
            point.Width = 7;
        }

        //  结构是会影响性能的值类型。 但根据使用方式的不同，这种影响可能是正向的影响，也可能是负向的影响。
        //  正面的影响是： 为结构分配内存时，速度非常快，因为它们将内联到对象里（在堆上） 或者是直接存在栈上
        //  负面的影响是:  只要是把结构作为参数传递，或者把一个结构赋值给另一个结构（如 A=B，其中A、B都是结构），结构的所有内容都被复制，而对于类，只复制引用。
        //                  这样就会有性能损失，根据结构的大小，性能损失程度不同。
        //  当把结构作为参数传递给方法时，应该把它作为ref参数进行传递，以避免性能损失。（此时值传递了结构在内存中的地址，这样传递速度就如同传递类的实例对象一样快了）但需如果这样做
        //                                                                          就必须注意被调用的方法会改变结构的值。
    }
}
